home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-2.iso / Files II / Prog / B-C / C++Source Code Fmtr.sit / Src / Parser.cp / Parser.cp
Encoding:
Text File  |  1992-04-28  |  6.8 KB  |  330 lines  |  [TEXT/MPS ]

  1. #ifndef __PARSER__
  2. #include "Parser.h"
  3. #endif    
  4.  
  5. #ifndef __PARSERACTIONS__
  6. #include "ParserActions.h"
  7. #endif    
  8.  
  9. #ifndef __CSCANNER__
  10. #include "CScanner.h"
  11. #endif    
  12.  
  13. #ifndef __FORMATTING__
  14. #include "Formatting.h"
  15. #endif    
  16.  
  17. #ifndef __CDENT__
  18. #include "cdent.h"
  19. #endif    
  20.  
  21. #ifndef __STACK__
  22. #include "Stack.h"
  23. #endif    
  24.  
  25. #ifndef __NEW__
  26. #include <new.h>
  27. #endif
  28.  
  29. #ifndef __STRING__
  30. #include <string.h>
  31. #endif
  32.  
  33.  
  34. //µ   Parser::IParser
  35. #pragma segment Parser
  36. short Parser::IParser()
  37. {
  38.     short err = fStack.IStack(100, 50);
  39.  
  40.     if (err != noErr)
  41.         return (err);
  42.  
  43.     fStack.SetEmptyItem(&gPrsDeclList);
  44.     Shift(&gPrsDeclList);
  45.     fItemIndex = 0;
  46.     fRecursionCount = 0;
  47.     fDepth = 0;
  48.     DebugParser(false);
  49.  
  50.     return (noErr);
  51. }
  52.  
  53.  
  54.  
  55. // µ   Parser::IParser
  56. #pragma segment Parser
  57. short Parser::IParser(const Parser *aParser)
  58. {
  59.     short err = fStack.IStack(&aParser->fStack);
  60.  
  61.     if (err != noErr)
  62.         return (err);
  63.  
  64.     fFormat = aParser->fFormat;
  65.     fItemIndex = aParser->fItemIndex;
  66.     fDebugParser = aParser->fDebugParser;
  67.  
  68.     return (noErr);
  69. }
  70.  
  71.  
  72.  
  73. //µ   Parser::~Parser
  74. #pragma segment Parser
  75. Parser::~Parser()
  76. {
  77. }
  78.  
  79.  
  80. //µ   Parser::Parse
  81. #pragma segment Parser
  82. Boolean Parser::Parse(Syntactic *aToken)
  83. {
  84.     /*
  85.     ** If this is a comment, handle it immediately
  86.     */
  87.     if (aToken->IsLex()) {
  88.         // Flush any identifiers which haven't been handled yet.
  89.         if (aToken->IsSeparator())
  90.             if (TopItem()->Type() == kSPrs_Id)
  91.                 if (!Parse())
  92.                     return (false);
  93.  
  94.         /*
  95.         ** Handle any special forms here, those forms which are unambiguous and
  96.         ** have but a single parse.  In particular, ids can become part of
  97.         ** operators (check if the top item on the parse stack is a Decl_Operator)
  98.         ** or parsed ids (check if the top items is a Prs_Id).
  99.         */
  100.         switch (aToken->Type()) {
  101.         case kSLex_DeclOperator:
  102.             Shift(new PrsDeclOperator);
  103.             break;
  104.  
  105.         case kSLex_Id:
  106.             if (TopItem()->Type() == kSPrs_DeclOperator)
  107.                 break;
  108.             // !!! FALL THROUGH !!!
  109.  
  110.         case kSLex_ClassColon:
  111.             // Identifiers might be qualified, etc.
  112.             if (TopItem()->Type() != kSPrs_Id)
  113.                 Shift(&gPrsId);
  114.             break;
  115.  
  116.         default:
  117.             break;
  118.         }
  119.     }
  120.  
  121.     /*
  122.     ** Debugging counter: prevent multiple invocations of the parser.
  123.     ** Incremented on entry, decremented on successful parse.
  124.     */
  125.     Boolean bumpRecursionCount = (Depth() >= fDepth);
  126.     if (bumpRecursionCount) {
  127.         if (++fRecursionCount >= 10) {
  128.             fFormat->Flush();
  129.             if (fDebugParser)
  130.                 DumpStack(gStderr);
  131.             diag(kFatal, "\n\Recursion limit: token = %s\n", NameOf(aToken->Type()));
  132.         }
  133.     }
  134.  
  135.     /*
  136.     ** Descend the stack looking for a taker.  If one is found, then
  137.     ** exit the routine.  If one is not found, return false.
  138.     */
  139.     if (fDebugParser) {
  140.         diag(kDebug, "\nEntry #%d Parser::Parse(%s)\n", fRecursionCount, NameOf(aToken->Type()));
  141.     }
  142.  
  143.     for (int i = Depth(); i-- > 0;) {
  144.         Syntactic * anItem = At(i);
  145.  
  146.         if (anItem->IsPrs()) {
  147.             // Preserve the item index around calls to parsers
  148.             short savedItemIndex = fItemIndex;
  149.  
  150.             fItemIndex = i;                        // Note this index
  151.             fDepth = Depth();                    // Note this depth
  152.             if (((SyntacticPrs *)anItem)->Accept(aToken, this)) {
  153.                 fItemIndex = savedItemIndex;    // Restore
  154.                 if (bumpRecursionCount)
  155.                     --fRecursionCount;
  156.  
  157.                 if (fDebugParser) {
  158.                     if (fRecursionCount == 0)
  159.                         DumpStack(gStderr);
  160.                 }
  161.  
  162.                 return (true);
  163.             }
  164.  
  165.             fItemIndex = savedItemIndex;        // Restore
  166.         }
  167.     }
  168.  
  169.     if (bumpRecursionCount)
  170.         --fRecursionCount;
  171.  
  172.     return (false);
  173. }
  174.  
  175.  
  176. /*
  177. **    Flush any tokens being held by any parse states on the stack.  Do this by
  178. ** parsing a token of type kSLex_Flush.  Because this parse usually fails,
  179. ** preserve and restore fRecursionCount around the call to Parse().  Return
  180. ** true because we don't care.
  181. */
  182. //µ   Parser::Parse
  183. #pragma segment Parser
  184. Boolean Parser::Parse()
  185. {
  186.     //short count = fRecursionCount;
  187.  
  188.     Parse(&gLexFlush);
  189.     //fRecursionCount = count;
  190.     return (true);
  191. }
  192.  
  193.  
  194.  
  195. //µ   Parser::FindHandle
  196. #pragma segment Parser
  197. short Parser::FindHandle(short aTokenType, const short *aStackDescription) const
  198. {
  199.     int stackDepth = Depth();
  200.  
  201.     // aStackDescription is of the form
  202.     //        <value> <tokenType> <n> {<n>*<v>}
  203.     // with the terminating condition of
  204.     //        (? < 0) <ignored> 0
  205.     for (;;) {
  206.         short aValue = *aStackDescription++;
  207.         short aType = *aStackDescription++;
  208.         short nItems = *aStackDescription++;
  209.         const short *nextDescription = &aStackDescription[nItems];
  210.  
  211.         // Match the token type first, as that is cheapest.  In case of
  212.         // mismatch, check nItems for 0.  If it is 0, then this was the
  213.         // last handle description.  Note that if this is the last handle
  214.         // description but that the token types matched, that the loop
  215.         // below will return true.  Consequently, there is no need for a
  216.         // separate check
  217.  
  218.         if (aValue < 0 && nItems == 0)
  219.             return (aValue);
  220.  
  221.         if (aTokenType == aType || aType < 0) {
  222.             // aStackDescription points to the deepest entry in the stack.
  223.             // Consequently, start indexing from the bottom to the top.
  224.             if (nItems <= stackDepth) {
  225.                 Boolean matched = true;
  226.  
  227.                 // Check out the values.
  228.                 while (matched && nItems > 0) {
  229.                     matched = (Pick(--nItems)->Type() == *aStackDescription) || (*aStackDescription < 0);
  230.                     ++aStackDescription;
  231.                 }
  232.  
  233.                 // If the stack matched, return the value
  234.                 if (matched)
  235.                     return (aValue);
  236.             }
  237.         }
  238.  
  239.         // The stack contents did not match the handle and there are more
  240.         // handles to check.  Advance to the next handle description
  241.         aStackDescription = nextDescription;
  242.     }
  243. }
  244.  
  245.  
  246. //µ   Parser::DumpStack
  247. #pragma segment Parser
  248. void Parser::DumpStack(StdFile &aFile)
  249. {
  250.     aFile.Puts("Dump of parse stack");
  251.     aFile.Puts("-------------------\n");
  252.     for (int i = 0; i < Depth(); i++) {
  253.         short aType = At(i)->Type();
  254.         char mark = (i == fItemIndex) ? '*' : ' ';
  255.  
  256.         aFile.Printf("%c %2d %-20s (%d)\n", mark, i, NameOf(aType), aType);
  257.     }
  258.     aFile.Flush();
  259. }
  260.  
  261.  
  262.  
  263. #define CASE(a)        case a: return (#a);
  264. #pragma segment Parser
  265. const char *Parser::NameOf(short aType)
  266. {
  267.     switch (aType) {
  268.         //ƒ-
  269.     CASE(kSLex_EOF)
  270.     CASE(kSLex_Id)
  271.     CASE(kSLex_Value)
  272.     CASE(kSLex_LParen)
  273.     CASE(kSLex_RParen)
  274.     CASE(kSLex_LBrace)
  275.     CASE(kSLex_RBrace)
  276.     CASE(kSLex_LCurly)
  277.     CASE(kSLex_RCurly)
  278.     CASE(kSLex_Op)
  279.     CASE(kSLex_OpAssign)
  280.     CASE(kSLex_Colon)
  281.     CASE(kSLex_ClassColon)
  282.     CASE(kSLex_SemiColon)
  283.     CASE(kSLex_Comma)
  284.     CASE(kSLex_Ellipsis)
  285.     CASE(kSLex_Comment)
  286.     CASE(kSLex_NewLine)
  287.     CASE(kSLex_Null)
  288.     CASE(kSLex_PoundLine)
  289.     CASE(kSLex_Break)
  290.     CASE(kSLex_Case)
  291.     CASE(kSLex_Default)
  292.     CASE(kSLex_Decl)
  293.     CASE(kSLex_DeclOperator)
  294.     CASE(kSLex_Do)
  295.     CASE(kSLex_Else)
  296.     CASE(kSLex_For)
  297.     CASE(kSLex_If)
  298.     CASE(kSLex_Struct)
  299.     CASE(kSLex_Switch)
  300.     CASE(kSLex_While)
  301.     CASE(kSLex_Public)
  302.  
  303.     CASE(kSLex_ParsedId)
  304.     CASE(kSLex_Flush)
  305.     CASE(kSLex_Context)
  306.  
  307.     CASE(kSPrs_Id)
  308.     CASE(kSPrs_StmtList)
  309.     CASE(kSPrs_DeclList)
  310.     CASE(kSPrs_DeclType)
  311.     CASE(kSPrs_Stmt)
  312.     CASE(kSPrs_Decl)
  313.     CASE(kSPrs_Do)
  314.     CASE(kSPrs_If)
  315.     CASE(kSPrs_Else)
  316.     CASE(kSPrs_For)
  317.     CASE(kSPrs_Struct)
  318.     CASE(kSPrs_Switch)
  319.     CASE(kSPrs_While)
  320.     CASE(kSPrs_Expr)
  321.     CASE(kSPrs_DeclOperator)
  322.     CASE(kSPrs_NewLine)
  323.     
  324.     default:    return ("<unknown token>");
  325.         //ƒ+
  326.     }
  327. }
  328.  
  329.  
  330.